package com.hup.sokoban.constant;

import com.hup.utils.swing.IconUtil;
import lombok.extern.log4j.Log4j2;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.function.Supplier;

/**
 * @author hugan
 * @date 2020/5/2
 */
@Log4j2
public class MapConstant {

    public static final String MAP_DIR = "./maps/";
    /**
     * 实现用户的自定义省缺背景图,{@link #MAP_DIR}下,以此开头的文件
     */
    public static final String USER_DEFAULT_BG_PREFIX = "background.";
    /**
     * 文件扩展名:已完成的设计图
     */
    public static final String EXT = ".map";
    /**
     * 文件扩展名:有问题/未完成的设计图
     */
    public static final String EXT_DESIGNING = ".map_designing";
    /**
     * 文件扩展名:游戏进度
     */
    public static final String EXT_PROGRESS = ".map_progress";
    /**
     * 文件扩展名:通关记录
     */
    public static final String EXT_WINNING = ".map_winning";

    public static final String INNER_BACKGROUND = "/img/map/background.png";

    //图像.st
    //图层1
    private static final Image IMG_WALL = IconUtil.getIcon("/img/map/wall.gif", "[围墙]图案").getImage();
    private static final Image IMG_BIRD = IconUtil.getIcon("/img/map/bird.gif", "[小鸟]图案").getImage();
    private static final Image IMG_ALI_LEFT = IconUtil.getIcon("/img/map/ali_left.gif", "[阿狸-l]图案").getImage();
    private static final Image IMG_ALI_FRONT = IconUtil.getIcon("/img/map/ali_front.gif", "[阿狸-f]图案").getImage();
    private static final Image IMG_ALI_RIGHT = IconUtil.getIcon("/img/map/ali_right.gif", "[阿狸-r]图案").getImage();
    private static final Image IMG_ALI_BACK = IconUtil.getIcon("/img/map/ali_back.gif", "[阿狸-b]图案").getImage();
    //图层2
    private static final Image IMG_CAGE = IconUtil.getIcon("/img/map/cage.gif", "[笼子]图案").getImage();
    //图像.ed

    /**
     * 地图元素类型
     */
    public enum ElementType {
        //一般类型属于图层1,在最底层
        EMPTY(0, null),
        WALL(1, () -> IMG_WALL),
        BIRD(2, () -> IMG_BIRD),
        ALI_LEFT(3, () -> IMG_ALI_LEFT),
        ALI_FRONT(4, () -> IMG_ALI_FRONT),
        ALI_RIGHT(5, () -> IMG_ALI_RIGHT),
        ALI_BACK(6, () -> IMG_ALI_BACK),
        /**
         * 笼子属于图层2,在顶层(会覆盖小鸟和阿狸)
         */
        CAGE(10, () -> IMG_CAGE),

        //带笼子的类型,用于关卡设计
        CAGE_ALI_FRONT(14, () -> getImage(14)),
        CAGE_BIRD(12, () -> getImage(12)),;

        /**
         * 元素的int值,不是与地图数据的intValue一一对应的
         */
        public final int intValue;
        private final Supplier<Image> drawer;
        /**
         * 用于缓存有笼子的二次绘制图像
         */
        private static final HashMap<Integer, Image> CAGE_CACHES = new HashMap<>();

        ElementType(int intValue, Supplier<Image> drawer) {
            this.intValue = intValue;
            this.drawer = drawer;
        }

        /**
         * @return 带笼子的intValue
         */
        public int intValueWithCage() {
            int layer1 = intValue % 10;
            return CAGE.intValue + layer1;
        }

        /**
         * 获取地图数据值对应的图像
         *
         * @param val 地图数据的值
         * @return nullable
         * @apiNote 异常的值不做处理和打印日志, 返回null
         */
        public static Image getImage(int val) {
            int layer1 = val % 10;
            int layer2 = val / 10 * 10;
            //只有笼子
            if (layer1 == EMPTY.intValue && layer2 == CAGE.intValue) {
                return CAGE.drawer.get();
            }

            Image res = null;
            for (ElementType type : values()) {
                if (type.intValue == layer1) {
                    res = type.drawer == null ? null : type.drawer.get();
                    break;
                }
            }
            if (layer2 != CAGE.intValue || res == null) {
                //没有笼子,或空图像
                return res;
            } else {
                //有笼子
                Image finalRes = res;
                return CAGE_CACHES.computeIfAbsent(val, mapValue2 -> {
                    log.debug("创建二次绘制图像, val={}", val);
                    BufferedImage cache = new BufferedImage(finalRes.getWidth(null), finalRes.getHeight(null), BufferedImage.TYPE_INT_ARGB);
                    Graphics2D g = cache.createGraphics();
                    g.drawImage(finalRes, 0, 0, cache.getWidth(), cache.getHeight(), null);
                    g.drawImage(IMG_CAGE, 0, 0, cache.getWidth(), cache.getHeight(), null);
                    g.dispose();
                    return cache;
                });
            }
        }

        public static boolean isAli(int val) {
            int layer1 = val % 10;
            return layer1 >= ALI_LEFT.intValue && layer1 <= ALI_BACK.intValue;
        }

        public static boolean hasCage(int val) {
            int layer2 = val / 10 * 10;
            return layer2 == CAGE.intValue;
        }

        /**
         * @return 该值图层1的类型
         */
        public static ElementType getLayer1(int val) {
            int layer1 = val % 10;
            for (ElementType type : values()) {
                if (type.intValue == layer1) {
                    return type;
                }
            }
            throw new IllegalArgumentException("错误值:" + val);
        }

    }

}
